package com.study.example.gameserver.module.scene.domain;

import com.sparrow.actor.AbstractActor;
import com.sparrow.common.aoi.domain.AOIEntity;
import com.sparrow.common.aoi.domain.Area;
import com.sparrow.common.aoi.domain.EntityType;
import com.sparrow.common.aoi.domain.MapData;
import com.sparrow.common.aoi.impl.ninegrid.AOIMap;
import com.sparrow.common.aoi.impl.ninegrid.NineGridAOISystem;
import com.sparrow.common.aoi.util.MapUtil;
import com.sparrow.common.tick.def.Tickable;
import com.study.example.gameserver.module.scene.entity.IEntity;
import com.study.example.gameserver.module.scene.entity.IMonsterEntity;
import com.study.example.gameserver.module.scene.entity.IPlayerEntity;
import com.study.example.gameserver.module.scene.entity.impl.DropItem;
import com.study.example.gameserver.module.scene.entity.impl.Monster;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

/**
 * 场景地图实例
 */
public class SceneMap extends AbstractActor implements AOIMap, Tickable {
    /**
     * 场景id
     */
    private int sceneId;
    /**
     * 线id
     */
    private int lineId;
    /**
     * 地图唯一id
     */
    private int mapId;
    /**
     * 区域数据
     */
    private Map<Integer, Area> areaMap = new ConcurrentHashMap<>();
    /**
     * 场景玩家
     */
    private ConcurrentHashMap<Long, IPlayerEntity> players = new ConcurrentHashMap<>();
    /**
     * 场景怪物
     */
    private ConcurrentHashMap<Long, IMonsterEntity> monsters = new ConcurrentHashMap<>();
    /**
     * 掉落物
     */
    private ConcurrentHashMap<Long, DropItem> dropItems = new ConcurrentHashMap<>();

    /**
     * aoi组件
     */
    private NineGridAOISystem aoiSystem;
    /**
     * 场景地图数据
     */
    private MapData mapData;

    public SceneMap(int sceneId, int lineId, int mapId, MapData mapData, Executor executor) {
        super(executor);
        this.sceneId = sceneId;
        this.lineId = lineId;
        this.mapId = mapId;
        this.mapData = mapData;
        this.aoiSystem = new NineGridAOISystem();
        int areaRows = mapData.getAreaRows();
        int areaCols = mapData.getAreaCols();
        // 直接遍历区域，而不是所有格子
        for (int row = 0; row < areaRows; row++) {
            for (int col = 0; col < areaCols; col++) {
                int areaId = MapUtil.getAreaId(col, row);
                areaMap.put(areaId, new Area(areaId));
            }
        }
    }

    public void setLineId(int lineId) {
        this.lineId = lineId;
    }

    public int getLineId() {
        return lineId;
    }

    public int getSceneId() {
        return sceneId;
    }

    public void setSceneId(int sceneId) {
        this.sceneId = sceneId;
    }

    public MapData getMapData() {
        return mapData;
    }

    public void setMapData(MapData mapData) {
        this.mapData = mapData;
    }

    public ConcurrentHashMap<Long, IPlayerEntity> getPlayers() {
        return players;
    }


    public int getMapId() {
        return mapId;
    }

    public void setMapId(int mapId) {
        this.mapId = mapId;
    }

    public void addPlayer(IPlayerEntity player) {
        players.put(player.getPlayerId(), player);
        aoiSystem.addAOIEntity(this, player, (int) player.getPos().getX(), (int) player.getPos().getZ());
    }

    public void addMonster(IMonsterEntity monster) {
        monsters.put(monster.getId(), monster);
        aoiSystem.addAOIEntity(this, monster, (int) monster.getPos().getX(), (int) monster.getPos().getZ());
    }

    public void addDropItem(DropItem item) {
        item.setMapId(this.getMapId());
        item.setSceneId(this.getSceneId());
        item.setLineId(this.getLineId());
        dropItems.put(item.getId(), item);
        aoiSystem.addAOIEntity(this, item, (int) item.getPos().getX(), (int) item.getPos().getZ());
    }


    public NineGridAOISystem getAoiSystem() {
        return aoiSystem;
    }

    public void removePlayer(IPlayerEntity player) {
        players.remove(player.getPlayerId());
        aoiSystem.removeAOIEntity(this, player);
    }

    public void removeEntity(IEntity entity) {
        EntityType entityType = entity.getEntityType();
        if (entityType.equals(EntityType.MONSTER)) {
            monsters.remove(entity.getAOIId());
        } else if (entityType.equals(EntityType.PLAYER)) {
            players.remove(entity.getAOIId());
        } else if (entityType.equals(EntityType.DROP_ITEM)) {
            dropItems.remove(entity.getAOIId());
        } else {
            return;
        }
        aoiSystem.removeAOIEntity(this, entity);
    }

    public Map<Integer, Area> getAreaMap() {
        return areaMap;
    }

    @Override
    public Area getArea(int areaId) {
        return areaMap.get(areaId);
    }

    public ConcurrentHashMap<Long, IMonsterEntity> getMonsters() {
        return monsters;
    }

    public void setMonsters(ConcurrentHashMap<Long, IMonsterEntity> monsters) {
        this.monsters = monsters;
    }

    public ConcurrentHashMap<Long, DropItem> getDropItems() {
        return dropItems;
    }

    @Override
    public void tick(long now, long delta) {
        for (IMonsterEntity monster : monsters.values()) {
            monster.tick(now, delta);
        }
    }


}
